package com.liying;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

public class LinkAlgorithm {
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void computeCommonNeighbors(Graph graph, Graph complementGraph) {
		Iterator iter = complementGraph.getAdjaxTable().entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			ArrayList<Edge> edges = (ArrayList<Edge>) entry.getValue();

			for (Edge edge : edges) {
				float score = 0;
				try {
					score = SetOperation.getIntersection(
							graph.getNeighbors(edge.getSource()),
							graph.getNeighbors(edge.getTarget())).size();
				} catch (NullPointerException ie) {
					// ie.printStackTrace();
				} finally {
					edge.setValue(score);
				}
			}
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void computeJaccardSimilarity(Graph graph, Graph complementGraph) {
		Iterator iter = complementGraph.getAdjaxTable().entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			ArrayList<Edge> edges = (ArrayList<Edge>) entry.getValue();

			for (Edge edge : edges) {
				float score = 0;
				try {
					float union = SetOperation.getUnion(
							graph.getNeighbors(edge.getSource()),
							graph.getNeighbors(edge.getTarget())).size();
					float intersection = SetOperation.getIntersection(
							graph.getNeighbors(edge.getSource()),
							graph.getNeighbors(edge.getTarget())).size();
					score = intersection / union;
				} catch (NullPointerException ie) {
					// ie.printStackTrace();
				} catch (ArithmeticException ex) {
					score = 0;
				} finally {
					edge.setValue(score);
				}
			}
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void computeAdamicAdar(Graph graph, Graph complementGraph) {
		Iterator iter = complementGraph.getAdjaxTable().entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			ArrayList<Edge> edges = (ArrayList<Edge>) entry.getValue();

			for (Edge edge : edges) {
				float score = 0;
				try {
					HashSet<String> intersection = SetOperation.getIntersection(
							graph.getNeighbors(edge.getSource()),
							graph.getNeighbors(edge.getTarget()));
					if (intersection.size() != 0) {
						float result = 0;
						for (String neighbor : intersection) {
							HashSet<String> neighbors = graph
									.getNeighbors(neighbor);
							double logValue = log2(graph.getNeighbors(neighbor)
									.size());
							if (neighbors != null && neighbors.size() != 0
									&& logValue != 0) {
								// 注意log2(1) = 0;
								result += 1 / logValue;
							}
						}
						score = result;
					}
				} catch (NullPointerException ie) {
					// ie.printStackTrace();
				} finally {
					edge.setValue(score);
				}
			}
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void computePreferentialAttachment(Graph graph, Graph complementGraph) {
		Iterator iter = complementGraph.getAdjaxTable().entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			ArrayList<Edge> edges = (ArrayList<Edge>) entry.getValue();

			for (Edge edge : edges) {
				float score = 0;
				try {
					score = graph.getNeighbors(edge.getSource()).size()
							* graph.getNeighbors(edge.getTarget()).size();
				} catch (NullPointerException ie) {
					// ie.printStackTrace();
				} finally {
					edge.setValue(score);
				}
			}
		}
	}
	
	private static double log2(double value) {
		return log(value, 2.0);
	}

	/**
	 * Math.log(3) = ln3 ���׹�ʽ��logx(y) =loge(y) / loge(x)
	 * 
	 * @param value
	 * @param base
	 * @return
	 */
	private static double log(double value, double base) {
		return Math.log(value) / Math.log(base);
	}
}
